package com.gbq.qimo.anno;

import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName TableMetadata
 * @Description TODO
 * @Author guobenqi
 * @Date 2021/5/29 11:01
 */
public class TableMetadata {
    private String tableName;

    private ColumnMetadata primaryKey;

    private List<ColumnMetadata> columns = new ArrayList<>();

    private String selectByIdSql;

    private Class entityClass;

    /**
     * 解析Mapper类构建表元数据信息
     *
     * @param mapperClass 具体的Mapper类入UserMapper
     */
    public TableMetadata(Class<?> mapperClass) {
        ResolvableType resolvableType = ResolvableType.forClass(mapperClass);

        ResolvableType baseMapperType = resolvableType.getInterfaces()[0];
        //获得泛型父接口的具体泛型类型，这里是具体的Entity类
        this.entityClass = baseMapperType.resolveGeneric(0);
        //获取实体类上注解的数据库表名
        Table tableName = AnnotationUtils.getAnnotation(entityClass, Table.class);
        this.tableName = tableName.value();
        //获取实体类属性上所有注解了@Column的属性的数据库表字段名
        for (int i = 0; i < entityClass.getDeclaredFields().length; i++) {
            ColumnMetadata columnMetadata = new ColumnMetadata();
            Field field = entityClass.getDeclaredFields()[i];
            //获取列名注解
            Column column = AnnotationUtils.getAnnotation(field, Column.class);
            if (column != null) {
                columnMetadata.setColumnIndex(i + 1);
                columnMetadata.setColumnName(column.value());
                ResolvableType columnResolvableType = ResolvableType.forField(field);
                columnMetadata.setJavaType(columnResolvableType.resolve());
                columnMetadata.setField(field);
                //解析主键字段
                PK pk = AnnotationUtils.getAnnotation(field, PK.class);
                if (pk != null) {
                    primaryKey = columnMetadata;
                }
                columns.add(columnMetadata);
            }
        }

        this.selectByIdSql = genSelectByIdSql();
    }

    public Class getEntityClass() {
        return entityClass;
    }

    public void setEntityClass(Class entityClass) {
        this.entityClass = entityClass;
    }

    public String getSelectByIdSql() {
        return selectByIdSql;
    }
    public String getInsertSql(){
        return genInsertSql();
    }

    public void setSelectByIdSql(String selectByIdSql) {
        this.selectByIdSql = selectByIdSql;
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public ColumnMetadata getPrimaryKey() {
        return primaryKey;
    }

    public void setPrimaryKey(ColumnMetadata primaryKey) {
        this.primaryKey = primaryKey;
    }

    public List<ColumnMetadata> getColumns() {
        return columns;
    }

    public void setColumns(List<ColumnMetadata> columns) {
        this.columns = columns;
    }


    /**
     * 生成一个select <columns> from <table> where pk=? 查询语句
     *
     * @return SelectByIdSql
     */
    public String genSelectByIdSql() {
        StringBuilder selectByIdBindSql = new StringBuilder("select ")
                .append(StringUtils.collectionToCommaDelimitedString(columns.stream().map(ColumnMetadata::getColumnName).collect(Collectors.toList())))
                .append(" from ").append(tableName).append(" where ").append(primaryKey.getColumnName() + " = ?");
        System.out.println(selectByIdBindSql.toString());
        return selectByIdBindSql.toString();
    }

    /**
     * 生成插入语句
     * */
    public String genInsertSql(){
        StringBuilder insertSql = new StringBuilder("insert into ").append(tableName)
                .append(StringUtils.collectionToCommaDelimitedString(columns.stream().map(ColumnMetadata::getColumnName).collect(Collectors.toList())))
                .append(" values(").
                append(columns.stream().map(ColumnMetadata::getColumnName).collect(Collectors.toList())).append(")");
        System.out.println(insertSql.toString());
        return insertSql.toString();


    }

}
